package com.breeze.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    static ReentrantLock mLock = new ReentrantLock(true);


    public static void main(String[] args) {
        /**
         * 方法一 公平锁 两线程交替执行
         */
       /* LockDemo lockDemo = new LockDemo();
        Thread thread = new Thread(lockDemo);
        Thread thread1 = new Thread(lockDemo);
        thread.start();
        thread1.start();*/
//        new MyThread1().start();
//        new MyThread2().start();

        /**
         * 方法二: 普通锁也可以实现两个线程交替执行
         */
        /*Method2Runnable runnable = new Method2Runnable();
        Thread thread = new Thread(runnable);
        Thread thread1 = new Thread(runnable);
        thread.start();
        thread1.start();*/

        /**
         * 方法三:  Condition的signal await
         */
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition = reentrantLock.newCondition();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            for (int i = 0; i < 20; i++) {
                reentrantLock.lock();
                condition.signal();
                System.out.println(Thread.currentThread().getName() + " " + i);
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        });
        executorService.execute(() -> {
            for (int i = 0; i < 20; i++) {
                reentrantLock.lock();
                condition.signal();
                System.out.println(Thread.currentThread().getName() + " " + i);
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        });
    }

    static class LockDemo implements Runnable {

        ReentrantLock lock = new ReentrantLock(true);

        @Override
        public void run() {
            for (int i = 1; i < 100; i++) {
                //获取锁
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                } finally {
                    //释放锁
                    lock.unlock();
                }
            }
        }
    }

    static class MyThread1 extends Thread {

        @Override
        public void run() {
            super.run();
            for (int i = 1; i < 20; i++) {
                //获取锁
                mLock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                } finally {
                    //释放锁
                    mLock.unlock();
                }
            }
        }
    }

    static class MyThread2 extends Thread {

        @Override
        public void run() {
            super.run();
            for (int i = 1; i < 20; i++) {
                //获取锁
                mLock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                } finally {
                    //释放锁
                    mLock.unlock();
                }
            }
        }
    }

    static class Method2Runnable implements Runnable {
        Object lock = new Object();

        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                synchronized (lock) {
                    try {
                        lock.notify();
                        System.out.println(Thread.currentThread().getName() + " " + i);
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
